﻿using UnityEngine;
using UniRx;

/// <summary>
/// 自制刚体，只附带简单物理模拟
/// </summary>
public class UnitPhysics : UnitComponentBase
{
    /// <summary>
    /// 触发器碰撞盒。用于伤害范围判定，而不用于物理。
    /// </summary>
    public Rigidbody2D rb => m_Rb ?? CreateRigidbody();
    private Rigidbody2D m_Rb;
    private Rigidbody2D CreateRigidbody()
    {
        m_Rb = entity.GetComponent<Rigidbody2D>();
        return m_Rb;
    }

    /// <summary>
    /// 速度
    /// </summary>
    public Vector2 velocity { get => rb.velocity; set => rb.velocity = value; }

    /// <summary>
    /// 是否开启模拟
    /// </summary>
    public bool simulated { get => rb.simulated; set => rb.simulated = value; }

    /// <summary>
    /// 是否使用重力
    /// </summary>
    public bool useGravity { get => !rb.isKinematic; set => rb.isKinematic = !value; }

    /// <summary>
    /// 触发器碰撞盒。用于伤害范围判定，而不用于物理。
    /// </summary>
    public BoxCollider2D box => m_Box ?? CreateBoxCollider();
    private BoxCollider2D m_Box;
    private BoxCollider2D CreateBoxCollider()
    {
        m_Box = entity.GetComponent<BoxCollider2D>();
        return m_Box;
    }


    /// <summary>
    /// 地面检测
    /// </summary>
    public GroundChecker groundChecker => m_GroundChecker ?? CreateGroundChecker();
    private GroundChecker m_GroundChecker;
    private GroundChecker CreateGroundChecker()
    {
        m_GroundChecker = entity.GetComponentInChildren<GroundChecker>();
        m_GroundChecker?.Init(entity);
        return m_GroundChecker;
    }


    /// <summary>
    /// 墙体检测
    /// </summary>
    public WallChecker wallChecker => m_WallChecker ?? CreateWallChecker();
    private WallChecker m_WallChecker;
    private WallChecker CreateWallChecker()
    {
        m_WallChecker = entity.GetComponentInChildren<WallChecker>();
        m_WallChecker?.Init(entity);
        return m_WallChecker;
    }


    /// <summary>
    /// 攀爬检测
    /// </summary>
    public ClimberChecker climberChecker => m_ClimberChecker ?? CreateClimberChecker();
    private ClimberChecker m_ClimberChecker;
    private ClimberChecker CreateClimberChecker()
    {
        m_ClimberChecker = entity.GetComponentInChildren<ClimberChecker>();
        m_ClimberChecker?.Init(entity);
        return m_ClimberChecker;
    }


    /// <summary>
    /// 边缘检测
    /// </summary>
    public EdgeChecker edgeChecker => m_EdgeChecker ?? CreateEdgeChecker();
    private EdgeChecker m_EdgeChecker;
    private EdgeChecker CreateEdgeChecker()
    {
        m_EdgeChecker = entity.GetComponentInChildren<EdgeChecker>();
        m_EdgeChecker?.Init(entity);
        return m_EdgeChecker;
    }

    protected override void OnSpawn()
    {
        velocity = Vector2.zero;
        simulated = true;
        box.enabled = true;
    }

    protected override void OnDespawn()
    {
        simulated = false;
        box.enabled = false;
    }

    protected override void OnThaw()
    {
        simulated = true;
        box.enabled = true;
    }

    protected override void OnFreeze()
    {
        simulated = false;
        box.enabled = false;
    }

    /// <summary>
    /// 刚体所受到的经过gravityScale缩放后的重力
    /// </summary>
    public float scaledGravity => rb.gravityScale * Mathf.Abs(Physics2D.gravity.y);

    /// <summary>
    /// 计算自由落体时的速度
    /// </summary>
    public float FFMEndSpeed(float freeFallHight)
    {
        return Mathf.Sqrt(2 * scaledGravity * freeFallHight);
    }
}